package wsi.match;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.rygh.core.util.UIo;
import org.rygh.core.xml.XmlPath;

import wsi.function.DirManager;

public class XmlFunctionalityController {
	public static final String DEFAULT_FILE = "functionality_xpath.txt";

	private final DirManager dir;
	private final List<XmlFunctionality> functionalities = new ArrayList<>();
	private final Map<String, XmlFunctionality> functionalityMap = new HashMap<>();

	private XmlPath masterPath;

	public XmlFunctionalityController(DirManager dir) {
		this.dir = dir;
	}

	public double getCompleteFunctionality(XmlPath xpath) {
		return getData(xpath, 2);
	}

	public double getCompleteInverseFunctionality(XmlPath xpath) {
		return getData(xpath, 3);
	}

	private double getData(XmlPath xpath, int index) {
		String val = xpath.stripIndex();

		if (functionalityMap.containsKey(val))
			return functionalityMap.get(val).get(index);

		for (XmlFunctionality i : functionalities) {
			// accept here is important

			if (i.accept(xpath)) {
				if (!functionalityMap.containsKey(val))
					functionalityMap.put(val, i);

				return i.get(index);
			}
		}

		// check if there is a corresponding self path

		val += "/" + XmlPath.SELF_TAG;

		if (functionalityMap.containsKey(val))
			return functionalityMap.get(val).get(index);

		// don't assert false here.
		System.out.println("[error] ghost xpath, lack of xml_func "
				+ xpath.getValue());
		return Double.NaN;
	}

	public XmlPath getMasterPath() {
		return masterPath;
	}

	public List<XmlFunctionality> getSortedList() {
		List<XmlFunctionality> list = new ArrayList<>();
		list.addAll(functionalities);

		Collections.sort(list, new Comparator<XmlFunctionality>() {

			@Override
			public int compare(XmlFunctionality o1, XmlFunctionality o2) {
				// descending
				return (int) (o2.getCompleteInverseFunctionality() * 10000. - o1
						.getCompleteInverseFunctionality() * 10000.);
			}
		});

		return list;
	}

	public boolean load() {
		File file = new File(dir.getFunctionDir(), DEFAULT_FILE);

		if (!file.exists())
			return false;

		String content = UIo.readFile(file);

		if (content.trim().isEmpty())
			return false;

		String[] lines = content.split("\r\n");
		XmlFunctionality func;

		double[] ds = new double[5];

		masterPath = new XmlPath(lines[0]);

		for (int i = 1; i < lines.length; i += 5) {
			for (int j = 0; j < 4; j++)
				ds[j] = Double.parseDouble(lines[i + j + 1]);

			func = new XmlFunctionality(lines[i]);
			func.setFunctionalities(ds);

			functionalities.add(func);
			functionalityMap.put(func.getName(), func);
		}

		return true;
	}

}
